package com.guodi.map.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.guodi.common.constant.StatusCode;
import com.guodi.common.utils.HttpRequester;
import com.guodi.common.utils.UuidUtil;
import com.guodi.core.boot.ctrl.BaseController;
import com.guodi.core.minio.util.MinioUtil;
import com.guodi.core.tool.api.R;
import com.guodi.map.entity.MapThematicTemplate;
import com.guodi.map.service.IMapThematicTemplateService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.csource.common.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;

/**
* @描述: 专题图模板表 前端控制器
* @作者: 陈宏成
* @日期: 2021-04-29
*/
@RestController
@RequestMapping("/MapThematicTemplate")
@Api(value = "API - MapThematicTemplateController", tags = "专题图模板表")
public class MapThematicTemplateController extends BaseController {

    @Resource
    private IMapThematicTemplateService iMapThematicTemplateService;

    /**
     * mxd模板文件服务器保存地址
     */
    @Value("${map.thematicMapTemplatePath}")
    private String mxdPath;

    /**
     * 内置的专题图模板，这两个不允许删除
     */
    private String[] builtinTemplateMxds = new String[]{"A3 Portrait.mxd","A3 Landscape.mxd"};

    /**
     * @描述：新增模板
     * @作者: 陈宏成
     * @日期: 2021-04-29
     */
    @PostMapping("/save")
    @ApiOperation(value = "新增模板")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "templateName", value = "模板名称", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "mxdFile", value = "mxd模板文件，add必须上传，update不上传不修改，delete和download不需要上传",required = true,  dataType = "file", paramType = "formData"),
            @ApiImplicitParam(name = "thumbnailImgFile", value = "缩略图图片文件，add必须上传，update不上传不修改，delete和download不需要上传",required = true,   dataType = "file", paramType = "formData"),
            @ApiImplicitParam(name = "soeUrl", value = "soe模板操作地址", required = true, dataType = "string", paramType = "query"),
    })
    @Transactional(rollbackFor = Exception.class)
    public R<MapThematicTemplate> save(String templateName, MultipartFile mxdFile
            , MultipartFile thumbnailImgFile, String soeUrl) throws IOException {
        // 验证数据
        if (!StringUtils.hasText(soeUrl)){
            return R.fail(StatusCode.ERROR_CODE_40005,"soe模板操作地址不能为空");
        }
        if (!StringUtils.hasText(templateName)){
            return R.fail(StatusCode.ERROR_CODE_40005,"专题模板名不能为空");
        }
        String operationType = "add";
        // 只有添加操作，才需要上传文件，其他操作无需要考虑
        if (mxdFile == null){
            return R.fail(StatusCode.ERROR_CODE_40005,"mxd模板必须上传");
        }
        if (thumbnailImgFile == null){
            return R.fail(StatusCode.ERROR_CODE_40005,"模板缩略图必须上传");
        }
        // 取时间戳做mxd文件名
        String templateFileName = UuidUtil.get32UUID();
        // 检查名字是否已经存在
        LambdaQueryWrapper<MapThematicTemplate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MapThematicTemplate::getName,templateName);
        int count = this.iMapThematicTemplateService.count(queryWrapper);
        if (count > 0){
            return R.fail(StatusCode.ERROR_CODE_40005,"模板名称已存在");
        }
        // 上传图片
        String fileId = MinioUtil.uploadFile(thumbnailImgFile.getInputStream(), "Map-Thematic-Template", thumbnailImgFile.getOriginalFilename());
        if (!StringUtils.hasText(fileId)){
            return R.fail(StatusCode.ERROR_CODE_40005,"缩略图上传失败");
        }
        // 上传soe的mxd文件
        HashMap<String, String> keyValueMap = new HashMap<>(4);
        keyValueMap.put("MxdName",templateFileName);
        keyValueMap.put("OperationType",operationType);
        keyValueMap.put("MxdPath", mxdPath);
        keyValueMap.put("f","pjson");
        keyValueMap.put("Mxd",new Base64().encode(mxdFile.getBytes()));
        String responseResult = HttpRequester.sendPostFile(soeUrl, keyValueMap,null,null);
        // 检查上传结果
        if (StringUtils.hasText(responseResult)){
            JSONObject result = JSONObject.parseObject(responseResult);
            if((result.containsKey("result") && result.getBoolean("result") == false) || result.containsKey("error")){
                // 上传模板失败，删除预览图
                MinioUtil.removeFile(fileId);
                return R.fail(StatusCode.ERROR_CODE_40005,"模板上传arcgis服务器失败");
            }
        }else{
            // 没有返回，上传模板失败，删除预览图
            MinioUtil.removeFile(fileId);
            return R.fail(StatusCode.ERROR_CODE_40005,"模板上传arcgis服务器失败");
        }
        // 构建对象
        MapThematicTemplate mapThematicTemplate = new MapThematicTemplate();
        mapThematicTemplate.setId(UuidUtil.get32UUID());
        mapThematicTemplate.setName(templateName);
        mapThematicTemplate.setThumbnailPath(fileId);
        mapThematicTemplate.setFileName(templateFileName);
        mapThematicTemplate.setCreateTime(new Date());
        mapThematicTemplate.setCreator(getUser().getUserId().toString());
        // 存库
        boolean save = this.iMapThematicTemplateService.save(mapThematicTemplate);
        if (save){
            // 返回
            return R.data(mapThematicTemplate);
        }else{
            MinioUtil.removeFile(fileId);
            return R.fail(StatusCode.ERROR_CODE_40005,"新增失败");
        }
    }

    /**
     * @描述：修改模板
     * @作者: 陈宏成
     * @日期: 2021-04-29
     */
    @PostMapping("/update")
    @ApiOperation(value = "修改模板")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "templateName", value = "模板名称", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "mxdFile", value = "mxd模板文件，不上传不修改", dataType = "file", paramType = "formData"),
            @ApiImplicitParam(name = "thumbnailImgFile", value = "缩略图图片文件，不上传不修改",  dataType = "file", paramType = "formData"),
            @ApiImplicitParam(name = "soeUrl", value = "soe模板操作地址", required = true, dataType = "string", paramType = "query"),
    })
    @Transactional(rollbackFor = Exception.class)
    public R<MapThematicTemplate> update(String id, String templateName, MultipartFile mxdFile, MultipartFile thumbnailImgFile, String soeUrl ) throws IOException {
        MapThematicTemplate mapThematicTemplate = new MapThematicTemplate();
        mapThematicTemplate.setId(id);
        mapThematicTemplate.setName(templateName);
        // 修改前的验证数据，填充数据
        R<MapThematicTemplate> prepareBeforeUpdateResult = this.prepareBeforeUpdate(mapThematicTemplate,mxdFile, soeUrl);
        if (prepareBeforeUpdateResult != null){
            return prepareBeforeUpdateResult;
        }
        String fileId = null;
        String oldThumbnailPath = null;
        if (thumbnailImgFile != null){
            // 上传图片
            fileId = MinioUtil.uploadFile(thumbnailImgFile.getInputStream(), "Map-Thematic-Template",thumbnailImgFile.getOriginalFilename());
            if (!StringUtils.hasText(fileId)){
                return R.fail(StatusCode.ERROR_CODE_40005,"缩略图上传失败");
            }
            // 删除旧图片
            MinioUtil.removeFile(mapThematicTemplate.getThumbnailPath());
            mapThematicTemplate.setThumbnailPath(fileId);
        }
        if (mxdFile != null){
            // 取时间戳做mxd文件名
            String templateFileName = UuidUtil.get32UUID();
            mapThematicTemplate.setFileName(templateFileName);
            // 上传soe的mxd文件
            HashMap<String, String> keyValueMap = new HashMap<>(5);
            keyValueMap.put("MxdName",templateFileName);
            keyValueMap.put("OperationType","add");
            keyValueMap.put("MxdPath", mxdPath);
            keyValueMap.put("f","pjson");
            keyValueMap.put("Mxd",new Base64().encode(mxdFile.getBytes()));
            String responseResult = HttpRequester.sendPostFile(soeUrl, keyValueMap,null,null);
            // 检查上传结果
            if (!StringUtils.hasText(responseResult) || (JSONObject.parseObject(responseResult).containsKey("result") && JSONObject.parseObject(responseResult).getBoolean("result") == false)){
                if(StringUtils.hasText(fileId)){
                    // 上传模板失败，删除预览图
                    MinioUtil.removeFile(fileId);
                    return R.fail(StatusCode.ERROR_CODE_40005,"模板上传arcgis服务器失败");
                }
            }
            // 删除旧的mxd文件
            MapThematicTemplate oldThematicTemplate = this.iMapThematicTemplateService.getById(mapThematicTemplate.getId());
            keyValueMap = new HashMap<>(4);
            keyValueMap.put("MxdName",oldThematicTemplate.getFileName());
            keyValueMap.put("OperationType","delete");
            keyValueMap.put("MxdPath", mxdPath);
            keyValueMap.put("f","pjson");
            HttpRequester.sendPostFile(soeUrl, keyValueMap,null,null);
        }
        this.iMapThematicTemplateService.updateById(mapThematicTemplate);
        return R.data(mapThematicTemplate);
    }


    /**
     * @描述：删除模板
     * @作者: 陈宏成
     * @日期: 2021-04-29
     */
    @PostMapping("/delete")
    @ApiOperation(value = "删除模板")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "soeUrl", value = "soe模板操作地址", required = true, dataType = "string", paramType = "query"),
    })
    @Transactional(rollbackFor = Exception.class)
    public R<MapThematicTemplate> delete(String id, String soeUrl ) throws IOException {
        // 验证非空数据项
        if (!StringUtils.hasText(id)){
            return R.fail(StatusCode.ERROR_CODE_40005,"主键id不能为空");
        }
        if (!StringUtils.hasText(soeUrl)){
            return R.fail(StatusCode.ERROR_CODE_40005,"soe地址不能为空");
        }

        MapThematicTemplate thematicTemplate = this.iMapThematicTemplateService.getById(id);
        if (thematicTemplate == null) {
            return R.fail(StatusCode.ERROR_CODE_40005,"记录不存在");
        }
        // 删除缩略图
        MinioUtil.removeFile(thematicTemplate.getThumbnailPath());
        // 删除mxd
        // 删除旧的mxd文件
        HashMap<String, String> keyValueMap = new HashMap<>(4);
        keyValueMap.put("MxdName",thematicTemplate.getFileName());
        keyValueMap.put("OperationType","delete");
        keyValueMap.put("MxdPath", mxdPath);
        keyValueMap.put("f","pjson");
        HttpRequester.sendPostFile(soeUrl, keyValueMap,null,null);
        this.iMapThematicTemplateService.removeById(id);
        return R.data(thematicTemplate);
    }


    /**
     * @描述：下载模板
     * @作者: 陈宏成
     * @日期: 2021-04-29
     */
    @PostMapping("/download")
    @ApiOperation(value = "下载模板")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "soeUrl", value = "soe模板操作地址", required = true, dataType = "string", paramType = "query"),
    })
    public void download(String id, String soeUrl , HttpServletResponse response) throws IOException {
        MapThematicTemplate thematicTemplate = this.iMapThematicTemplateService.getById(id);
        // 返回
        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-Type", "application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(thematicTemplate.getName() + ".mxd", "UTF-8"));
        ServletOutputStream outputStream = response.getOutputStream();
        // 下载的mxd文件
        HashMap<String, String> keyValueMap = new HashMap<>(4);
        keyValueMap.put("MxdName",thematicTemplate.getFileName());
        keyValueMap.put("OperationType","download");
        keyValueMap.put("MxdPath", mxdPath);
        keyValueMap.put("f","mxd");
        HttpRequester.sendPostFile(soeUrl, keyValueMap,null,outputStream);

    }


    /**
     * @描述：分页获取，同时检查内置模板是否正常在系统中，如果没有，则新增
     * @作者: 陈宏成
     * @日期: 2021-04-29
     */
    @PostMapping("/page")
    @ApiOperation(value = "分页获取，同时检查内置模板是否正常在系统中，如果没有，则新增")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "size", value = "页面大小", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "current", value = "当前页码",  dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "templateName", value = "模板名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "soeUrl", value = "模板操作soe地址，如果没有内置模板时，会自动补充",required = true,  dataType = "string", paramType = "query"),
    })
    public R<Page<MapThematicTemplate>> page(@ApiIgnore Page page, String templateName, String soeUrl) throws IOException {
        LambdaQueryWrapper<MapThematicTemplate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(templateName),MapThematicTemplate::getName,templateName);
        Page<MapThematicTemplate> page1 = this.iMapThematicTemplateService.page(page, queryWrapper);
        return R.data(page1);
    }

    /**
     * @描述：修改前的准备，包括验证数据和填充数据
     * @入参：
     * @出参：如果返回null，则表示无任何问题，如果有返回，则说明有问题需要返回给前端
     * @作者: 陈宏成
     * @日期: 2021-03-30
     */
    private R<MapThematicTemplate> prepareBeforeUpdate(MapThematicTemplate mapThematicTemplate, MultipartFile mxdFile, String soeUrl){
        // 验证非空数据项
        if (!StringUtils.hasText(mapThematicTemplate.getId())){
            return R.fail(StatusCode.ERROR_CODE_40005,"主键id不能为空");
        }
        if (!StringUtils.hasText(mapThematicTemplate.getName())){
            return R.fail(StatusCode.ERROR_CODE_40005,"模板名不能为空");
        }
        if (!StringUtils.hasText(soeUrl)){
            return R.fail(StatusCode.ERROR_CODE_40005,"soe地址不能为空");
        }

        // 验证重名数据项
        LambdaQueryWrapper<MapThematicTemplate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MapThematicTemplate::getName,mapThematicTemplate.getName() );
        queryWrapper.ne(MapThematicTemplate::getId,mapThematicTemplate.getId() );
        int count = this.iMapThematicTemplateService.count(queryWrapper);
        if (count > 0){
            return R.fail(StatusCode.ERROR_CODE_40005,"该模板名已存在");
        }
        MapThematicTemplate thematicTemplate = this.iMapThematicTemplateService.getById(mapThematicTemplate.getId());
        if (thematicTemplate == null ){
            return R.fail(StatusCode.ERROR_CODE_40005,"记录不存在");
        }

        mapThematicTemplate.setFileName(thematicTemplate.getFileName());
        mapThematicTemplate.setThumbnailPath(thematicTemplate.getThumbnailPath());

        mapThematicTemplate.setModifier(getUser().getUserId().toString());
        mapThematicTemplate.setModifyTime(new Date());
        return null;
    }


}
